﻿using UnityEngine;
using System.Collections;

/// <summary>
/// Unity singleton.
/// http://redframe-game.com/blog/global-managers-with-generic-singletons/
/// http://www.unitymanual.com/thread-16916-1-1.html
/// 例子: public class TestManger : CESingleton<TestManger>{}
/// </summary>
public class CESingleton<T> : MonoBehaviour where T : Component
{

	private static bool mIsQuitApplication = false;
	private static T mInstance;

	public static T Instance {
		get {
			if (mIsQuitApplication) {
				Debug.LogError ("Try To Call CESingleton Get Instance When The Application Already Quit, return null inside");
				return null;
			}
			if (mInstance == null) {
				mInstance = FindObjectOfType<T> ();
				if (mInstance == null) {
					GameObject go = new GameObject ();
					go.name = "*CESingleton Auto Delete When Quit";
//					obj.hideFlags = HideFlags.HideAndDontSave;
					mInstance = go.AddComponent<T> ();
				}
			}
			return mInstance;
		}
	}

	/// <summary>
	/// 注意!! 子类不要存在Awake方法, 因为Unity直接映射到相应函数所以子类即使
	/// 声明为Private也会调用子类而不调用父类方法,同时如果在Awake中连锁的又调用到
	///	当前这个类的Instance实例那么则会循环初始化N个实例对象
	///		
	///	注意!! 不要调用Awake而是override DoAwake方法
	/// </summary>
	protected void Awake ()
	{
		//提前在Awake方法内部设置mInstance变量,防止在DoAwake方法中调用到当前类的Instance方法从而循环New出新的对象
		if (mInstance == null) {
			mInstance = this as T;
		} else {
			//出于某种原因(@see mIsQuitApplication) 
			//在结束编辑器时候该变量被保存到了Hierarchy中,此时需要手动在Hierarchy中删除该变量
			Debug.LogError ("Check is hava GameObject named *CESingleton Auto Delete When Quit in hierarchy, if so delete it");
		}
		if (!IsDisposeWhenQuitLevel ()) {
			DontDestroyOnLoad (this.gameObject);
		}
		DoAwake ();
	}

	protected virtual void DoAwake ()
	{
	}

	/// <summary>
	/// 指明当前单例是否需要在加载新的关卡时候被Dispose掉,默认为Flase及全局仅存在一个实例
	/// </summary>
	protected virtual bool IsDisposeWhenQuitLevel ()
	{
		return false;
	}

	void OnApplicationQuit ()
	{
		mIsQuitApplication = true;
		Destroy (this.gameObject);
	}

}
